package TokenRecognizer;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author jefoutta
 */
public class AFNSimulator {
    Automata afn = new Automata();
    Sets<State> set;
    State end;
    boolean found;

    public boolean simulate(String s, Automata tautomata){
        afn.join(tautomata);
        set = eLock(afn.getFirstState());
        for(int i = 0; i < s.length(); i++){
            set = eLock(move(set,new Transition(s.charAt(i))));
        }
        end = new State(set);
        found = end.getAcceptation();
        
        return found;
    }

    private Sets<State> eLock(State s){
        Sets<State> afnStateSet = new Sets();
        Integer k = 0;
        do{
            for(int i = 0; i < afn.getSize(); i++){
                if(afn.getTransition(s, afn.getState(i)) != null){
                    if(afn.getTransition(s, afn.getState(i)).getLabel() == 'e'){
                        if(!afnStateSet.contains(afn.getState(i))){
                            afnStateSet.add(afn.getState(i));
                        }
                    }
                }
            }
            k++;
            if(k < afnStateSet.getSize())
                s = afnStateSet.get(k);
        }while(k < afnStateSet.getSize());

        /*if(!afdStateSet.contains(afnStateSet)){
            afdStateSet.add(afnStateSet);
        }*/
        return afnStateSet;
    }

    private Sets<State> eLock(Sets<State> set1){
        Sets<State> tset = new Sets();
        for(int i = 0; i < set1.getSize(); i++){
            tset.union(eLock(set1.get(i)));
        }
        return tset;
    }

    private Sets<State> move(State s,Transition t){
        Sets<State> afnStateSet = new Sets();
        Integer k = 0;
        do{
            for(int i = 0; i < afn.getSize(); i++){
                if(afn.getTransition(s, afn.getState(i)) != null){
                    if(afn.getTransition(s, afn.getState(i)).getLabel() == t.getLabel()){
                        if(!afnStateSet.contains(afn.getState(i))){
                            afnStateSet.add(afn.getState(i));
                        }
                    }
                }
            }
            k++;
            if(k < afnStateSet.getSize())
                s = afnStateSet.get(k);
        }while(k < afnStateSet.getSize());

        /*if(!afdStateSet.contains(afnStateSet)){
            afdStateSet.add(afnStateSet);
        }*/
        return afnStateSet;
    }

    private Sets<State> move(Sets<State> set1, Transition t){
        Sets<State> tset = new Sets();
        for(int i = 0; i < set1.getSize(); i++){
            tset.union(move(set1.get(i), t));
        }
        return tset;
    }
}
